import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:x3_charts_core/chart_tools/chart_tools.dart';
import 'package:x3_charts_core/model/general_chart_model.dart';
import 'package:x3_charts_core/touch_fnfo/point_touch_info.dart';

///**
///* @author hrongyong
///* @date   3/1/21
///* @email hrongyong@gmail.com
///* Description:
///*/
class AbreastHistogramChartPainter extends CustomPainter {
  ///图表信息
  final List<GeneralChartModel> chartList;

  ///左边Y轴最大值
  int leftYAxisMax;

  ///左边Y轴的单位
  String leftYAxisUnit;

  ///右边Y轴最大值
  int rightYAxisMax;

  ///右边Y轴的单位
  String rightYAxisUnit;

  ///背景色
  Color backgroundColor;

  ///x轴线颜色
  final Color xAxisColor;

  ///x轴线描述颜色
  final Color xAxisDescriptionColor;

  ///y轴线颜色
  final Color yAxisColor;

  ///y轴线描述颜色
  final Color yAxisDescriptionColor;

  ///绘制Y轴线
  final bool drawYAxis;

  ///第一个直方的颜色
  final Color firstHistogramColor;

  ///第二根直方的颜色
  final Color secondHistogramColor;

  ///第一个折线的颜色
  final Color firstPolylineColor;

  final PointTouchInfo pointTouchInfo;

  ///第一个直方描述的前缀
  final String firstHistogramPrefix;

  ///第二个直方描述的前缀
  final String secondHistogramPrefix;

  ///第一个折线描述的前缀
  final String firstPolylinePrefix;

  ///是否显示描述
  final bool showDescription;

  ///是否点击点显示信息
  final bool clickTheDotsShowInfo;

  AbreastHistogramChartPainter({
    @required this.chartList,
    @required this.leftYAxisMax,
    @required this.rightYAxisMax,
    @required this.pointTouchInfo,
    this.leftYAxisUnit = "",
    this.rightYAxisUnit = "",
    this.backgroundColor = Colors.white,
    this.xAxisColor = Colors.black12,
    this.yAxisColor = Colors.black12,
    this.xAxisDescriptionColor = Colors.black,
    this.yAxisDescriptionColor = Colors.black,
    this.drawYAxis = true,
    this.firstHistogramColor = const Color(0xFF727FC7),
    this.secondHistogramColor = const Color(0xFFC0C4DB),
    this.firstPolylineColor = const Color(0xFFD695AB),
    this.firstHistogramPrefix = "",
    this.secondHistogramPrefix = "",
    this.firstPolylinePrefix = "",
    this.showDescription = false,
    this.clickTheDotsShowInfo = true,
  }) : super(repaint: pointTouchInfo);

  ///左边间距
  double leftMargin = 0.0;

  ///右边间距
  double rightMargin = 0.0;

  ///底部间距
  double bottomMargin = 0.0;

  ///间距
  EdgeInsets chartPadding;

  double maxWidth = 0.0;
  double maxHeight = 0.0;
  double xStep = 0.0; // x 间隔
  double yStep = 0.0; // y 间隔
  ///轴线画笔
  Paint axisPaint = Paint()..strokeWidth = 1.0;

  ///文字
  final TextPainter _textPainter = TextPainter(textDirection: TextDirection.ltr);

  //直方图的填充颜色
  Paint fillPaint = Paint()..color = Colors.red;

  final List<Offset> firstPolyLineOffset = []; // 折线点位信息

  //折线
  Paint linePaint = Paint()
    ..color = Colors.red
    ..strokeCap = StrokeCap.round
    ..strokeJoin = StrokeJoin.round
    ..style = PaintingStyle.stroke;

  @override
  void paint(Canvas canvas, Size size) {
    if (chartList == null || chartList.length == 0) return;

    ///确定左边和下边的距离
    TextPainter painter01 = TextPainter(
        maxLines: 1,
        textDirection: TextDirection.ltr,
        text: TextSpan(
            text: leftYAxisMax.toString() + leftYAxisUnit,
            style: TextStyle(
              fontSize: 10,
            )));
    painter01.layout();
    leftMargin = painter01.width;
    bottomMargin = painter01.height;

    ///确定右边的距离
    TextPainter painter02 = TextPainter(
        maxLines: 1,
        textDirection: TextDirection.ltr,
        text: TextSpan(
            text: rightYAxisMax.toString() + rightYAxisUnit,
            style: TextStyle(
              fontSize: 10,
            )));
    painter02.layout();
    rightMargin = painter02.width;
    chartPadding = EdgeInsets.only(left: leftMargin + 2, bottom: bottomMargin + 4, right: rightMargin + 4, top: 10);

    ///可绘画的宽度
    maxWidth = size.width - chartPadding.left - chartPadding.right;

    /// x 间隔
    xStep = maxWidth / chartList.length;

    ///可绘画的高度
    maxHeight = size.height - chartPadding.top - chartPadding.bottom;

    /// y 间隔
    yStep = maxHeight / 10;

    ///绘制背景
    canvas.drawRect(Offset.zero & size, Paint()..color = backgroundColor);

    ///移动绘画中心
    canvas.translate(chartPadding.left, size.height - chartPadding.bottom);

    ///绘制X轴刻度和文本
    drawXAxisScaleAndText(canvas, size);

    ///绘制左边Y轴刻度和文本
    drawLeftYAxisScaleAndText(canvas, size);

    ///绘制右边Y轴刻度和文本
    drawRightYAxisScaleAndText(canvas, size);

    ///绘制直方图和描述
    drawHistogramAndDescription(canvas, size);

    ///绘制折线
    ///收集点位
    locationOfCollectionPoint(canvas, size);

    ///是否要绘制第一根折线
    double firstValue = 0.0;
    firstPolyLineOffset.forEach((element) {
      firstValue = (element.dy == 0.0 || element.dy == -1) ? firstValue : element.dy;
    });
    if (firstValue != 0.0) drawLineChart(canvas: canvas, line: firstPolyLineOffset, lineColor: firstPolylineColor);

    ///绘制第一根折线的点
    if (firstValue != 0.0) drawDots(canvas: canvas, line: firstPolyLineOffset, drawColor: firstPolylineColor, size: size);
    if (showDescription) drawDescriptionText(canvas, size, firstPolyLineOffset, firstPolylineColor, isDraw: firstValue != 0.0);
  }

  drawDescriptionText(Canvas canvas, Size size, List<Offset> offsetList, Color color, {bool isDraw = true}) {
    if (!isDraw) return;
    for (var i = 0; i < offsetList.length; i++) {
      drawDescription(canvas, offsetList, chartList[i].firstPolylineDescription, color, i);
    }
  }

  drawDescription(Canvas canvas, List<Offset> offsetList, String description, Color color, int index) {
    ///绘制标题
    TextSpan text = TextSpan(text: description, style: TextStyle(fontSize: 10, color: color));
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    Size textSize = _textPainter.size;
    Offset textOffsetPos;
    if (index == 0 && offsetList.length == 1) {
      ///唯一一个点
      textOffsetPos = Offset(offsetList[index].dx, offsetList[index].dy - textSize.height);
    } else if (index == 0 && offsetList.length != 1) {
      ///第一个点
      double a = ChartTools.getAngleByThreeP(a: Offset(0, -maxHeight + 1), b: offsetList[index], c: offsetList[index + 1]) * 180 / pi;
      if (a >= 90) {
        ///钝角
        textOffsetPos = Offset(offsetList[index].dx, offsetList[index].dy - textSize.height * 1.5);
      } else {
        ///锐角
        textOffsetPos = Offset(offsetList[index].dx, offsetList[index].dy + textSize.height / 2);
      }
    } else if (offsetList.length != 1 && index == offsetList.length - 1) {
      ///最后一个点
      double a = ChartTools.getAngleByThreeP(a: offsetList[index - 1], b: offsetList[index], c: Offset(offsetList[index].dx, -maxHeight - 1)) * 180 / pi;
      if (a >= 90) {
        ///钝
        textOffsetPos = Offset(offsetList[index].dx - textSize.width, offsetList[index].dy - textSize.height * 1.5);
      } else {
        ///锐角
        textOffsetPos = Offset(offsetList[index].dx - textSize.width, offsetList[index].dy + textSize.height / 2);
      }
    } else {
      ///非首尾点
      double a = ChartTools.getAngleByThreeP(a: offsetList[index - 1], b: offsetList[index], c: Offset(offsetList[index].dx, -maxHeight - 1)) * 180 / pi;
      double b = ChartTools.getAngleByThreeP(a: Offset(0, -maxHeight - 1), b: offsetList[index], c: offsetList[index + 1]) * 180 / pi;
      if (a + b >= 180) {
        textOffsetPos = Offset(offsetList[index].dx - textSize.width / 2, offsetList[index].dy - textSize.height * 1.5);
      } else {
        textOffsetPos = Offset(offsetList[index].dx - textSize.width / 2, offsetList[index].dy + textSize.height / 3);
      }
    }
    _textPainter.paint(canvas, textOffsetPos);
  }

  drawDots({@required Canvas canvas, @required List<Offset> line, @required Color drawColor, Size size}) {
    for (int i = 0; i < chartList.length; i++) {
      if (clickTheDotsShowInfo && pointTouchInfo.point != null) {
        Rect rect = Rect.fromCircle(radius: 15, center: line[i]);

        ///点击的位置
        Offset clickedPosition = Offset(pointTouchInfo.point.dx - leftMargin, pointTouchInfo.point.dy - size.height + bottomMargin);
        if (rect.contains(clickedPosition)) {
          canvas.drawCircle(line[i], 5, Paint()..color = drawColor);
          canvas.drawCircle(line[i], 4, Paint()..color = Colors.white);
          canvas.drawCircle(line[i], 3, Paint()..color = drawColor);

          ///顶部绘制信息
          if (clickTheDotsShowInfo) _topDrawInformation(canvas, size, i, line[i]);
        } else {
          canvas.drawCircle(line[i], 3, Paint()..color = drawColor);
        }
      } else {
        canvas.drawCircle(line[i], 3, Paint()..color = drawColor);
      }
    }
  }

  _topDrawInformation(Canvas canvas, Size size, int index, Offset offset) {
    TextStyle style = TextStyle(fontSize: 8, color: Colors.black);
    TextSpan text;
    Size textSize;
    Offset textOffsetPos;

    ///绘制标题
    text = TextSpan(text: firstHistogramPrefix + chartList[index].firstHistogramDescription, style: style);
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    textSize = _textPainter.size;
    textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy - textSize.height * 3 - 4);
    _textPainter.paint(canvas, textOffsetPos);

    ///绘制下一级别标题
    text = TextSpan(text: secondHistogramPrefix + chartList[index].secondHistogramDescription, style: style);
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    textSize = _textPainter.size;
    textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy - textSize.height * 2 - 3);
    _textPainter.paint(canvas, textOffsetPos);

    ///绘制下一级别标题
    text = TextSpan(text: firstPolylinePrefix + chartList[index].firstPolylineDescription, style: style);
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    textSize = _textPainter.size;
    textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy - textSize.height - 2);
    _textPainter.paint(canvas, textOffsetPos);
  }

  drawLineChart({@required Canvas canvas, @required List<Offset> line, @required Color lineColor}) {
    Offset p1 = line[0];
    Path path = Path()..moveTo(p1.dx, p1.dy);
    for (var i = 1; i < line.length; i++) {
      if (line[i].dy != -1) {
        path.lineTo(line[i].dx, line[i].dy);
      }
    }
    linePaint..strokeWidth = 1;
    linePaint..color = lineColor;
    PathMetrics pms = path.computeMetrics();
    pms.forEach((pm) {
      canvas.drawPath(pm.extractPath(0, pm.length), linePaint..strokeWidth = 2);
    });
  }

  ///收集点位
  locationOfCollectionPoint(Canvas canvas, Size size) {
    firstPolyLineOffset.clear();
    for (int i = 0; i < chartList.length; i++) {
      firstPolyLineOffset.add(_generatePointsOffset(lineValue: chartList[i].firstPolyline, index: i));
    }
  }

  Offset _generatePointsOffset({@required double lineValue, @required int index}) {
    Offset returnOffset;
    if (lineValue != null) {
      double dataHeight = -(lineValue * maxHeight);
      returnOffset = Offset(xStep * index + xStep / 2, dataHeight);
    } else {
      returnOffset = Offset(xStep * index + xStep / 2, -1);
    }
    return returnOffset;
  }

  drawHistogramAndDescription(Canvas canvas, Size size) {
    canvas.save();
    canvas.translate(xStep / 2, 0);
    for (int i = 0; i < chartList.length; i++) {
      double firstHeight = -chartList[i].firstHistogram * maxHeight;
      Rect firstRect = Rect.fromLTWH(0, 0, xStep / 3, firstHeight).translate(-xStep / 3 - 1, 0);
      fillPaint..color = firstHistogramColor;

      ///绘制第一个直方
      canvas.drawRect(firstRect, fillPaint);

      ///绘制文本
      if (showDescription)
        _drawHistogramDescriptionText(
          canvas,
          title: chartList[i].firstHistogramDescription,
          offset: Offset(-(xStep / 3 + 1) / 2, firstHeight / 2),
        );
      fillPaint..color = secondHistogramColor;
      double secondHeight = -chartList[i].secondHistogram * maxHeight;
      Rect secondRect = Rect.fromLTWH(0, 0, xStep / 3, secondHeight).translate(1, 0);

      ///绘制第二个直方
      canvas.drawRect(secondRect, fillPaint);

      ///绘制文本
      if (showDescription)
        _drawHistogramDescriptionText(
          canvas,
          title: chartList[i].secondHistogramDescription,
          offset: Offset((xStep / 3 + 1) / 2, secondHeight / 2),
        );

      canvas.translate(xStep, 0);
    }
    canvas.restore();
  }

  void _drawHistogramDescriptionText(
    Canvas canvas, {
    String title,
    Offset offset = Offset.zero,
    double fontSize = 6,
    Color color = Colors.black,
  }) {
    ///绘制标题
    TextSpan text = TextSpan(text: title, style: TextStyle(fontSize: fontSize, color: color));
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    Size textSize = _textPainter.size;
    Offset textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy - textSize.height / 2);
    _textPainter.paint(canvas, textOffsetPos);
  }

  drawRightYAxisScaleAndText(Canvas canvas, Size size) {
    canvas.save();
    canvas.translate(maxWidth, 0);

    ///Y轴线
    if (drawYAxis) canvas.drawLine(Offset.zero, Offset(0, -maxHeight), axisPaint..color = yAxisColor);
    for (int i = 0; i <= 10; i++) {
      canvas.drawLine(Offset.zero, Offset(-4, 0), axisPaint..color = xAxisColor);
      _drawRightYAxisText(canvas, title: (rightYAxisMax / 10 * i).toInt().toString() + rightYAxisUnit, offset: Offset.zero);
      canvas.translate(0, -yStep);
    }

    canvas.restore();
  }

  ///绘制右边Y轴文字
  void _drawRightYAxisText(
    Canvas canvas, {
    String title,
    Offset offset = Offset.zero,
    double fontSize = 6,
    Color color = Colors.black,
  }) {
    ///绘制标题
    TextSpan text = TextSpan(text: title, style: TextStyle(fontSize: fontSize, color: color));
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    Size textSize = _textPainter.size;
    Offset textOffsetPos = Offset(offset.dx, offset.dy - textSize.height / 2);
    _textPainter.paint(canvas, textOffsetPos);
  }

  drawLeftYAxisScaleAndText(Canvas canvas, Size size) {
    canvas.save();

    ///Y轴线
    if (drawYAxis) canvas.drawLine(Offset.zero, Offset(0, -maxHeight), axisPaint..color = yAxisColor);
    for (int i = 0; i <= 10; i++) {
      canvas.drawLine(Offset.zero, Offset(-4, 0), axisPaint..color = xAxisColor);
      _drawLeftYAxisText(canvas, title: (leftYAxisMax / 10 * i).toInt().toString() + leftYAxisUnit, offset: Offset.zero);
      canvas.translate(0, -yStep);
    }

    canvas.restore();
  }

  ///绘制左边Y轴文字
  void _drawLeftYAxisText(
    Canvas canvas, {
    String title,
    Offset offset = Offset.zero,
    double fontSize = 6,
    Color color = Colors.black,
  }) {
    ///绘制标题
    TextSpan text = TextSpan(text: title, style: TextStyle(fontSize: fontSize, color: color));
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    Size textSize = _textPainter.size;
    Offset textOffsetPos = Offset(offset.dx - textSize.width - 4, offset.dy - textSize.height / 2);
    _textPainter.paint(canvas, textOffsetPos);
  }

  drawXAxisScaleAndText(Canvas canvas, Size size) {
    canvas.save();

    ///x轴线
    canvas.drawLine(Offset.zero, Offset(maxWidth, 0), axisPaint..color = xAxisColor);

    ///移动到第一个点
    canvas.translate(xStep / 2, 0);

    ///x轴刻度线
    for (int i = 0; i < chartList.length; i++) {
      canvas.drawLine(Offset.zero, Offset(0, 3), axisPaint..color = xAxisColor);

      ///x轴线描述
      _drawXAxisText(canvas, title: chartList[i].name, offset: Offset.zero);
      canvas.translate(xStep, 0);
    }

    canvas.restore();
  }

  ///绘制X轴文字
  void _drawXAxisText(
    Canvas canvas, {
    String title,
    Offset offset = Offset.zero,
    double fontSize = 5,
    Color color = Colors.black,
  }) {
    ///绘制标题
    TextSpan text = TextSpan(text: title, style: TextStyle(fontSize: fontSize, color: color));
    _textPainter.text = text;
    _textPainter.layout(); // 进行布局
    Size textSize = _textPainter.size;
    Offset textOffsetPos = Offset(offset.dx - textSize.width / 2, offset.dy + textSize.height / 3);
    _textPainter.paint(canvas, textOffsetPos);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
